//
//  String+Extension.swift
//  Swift-framwork
//
//  Created by 周保勇 on 2019/3/28.
//  Copyright © 2019 周保勇. All rights reserved.
//

import Foundation
import UIKit
import CommonCrypto

extension String {
    
    /// 随机生成字符串
    ///
    /// - Parameter length: 字符串长度
    static func random(of length: Int) -> String {
        var strArray:Array<String> = Array()
        while strArray.count < length {
            let a:Int = Int(arc4random() % 127)
            let c:Character = Character(UnicodeScalar(a)!)
            // 数字
            if a > 47 && a < 58 {
                strArray.append(String.init(c))
            }
            // 大写字母
            if a > 64 && a < 92 {
                strArray.append(String.init(c))
            }
            // 小写字母
            if a > 96 && a < 123 {
                strArray.append(String.init(c))
            }
        }
//        for _ in 0...length {
//            let a:Int = Int(arc4random() % 127)
//            let c:Character = Character(UnicodeScalar(a)!)
////            if a > 32 && a < 127 {
////                strArray.append(String.init(c))
////            }
//            // 数字
//            if a > 47 && a < 58{
//                strArray.append(String.init(c))
//            }
//            // 大写字母
//            if a > 64 && a < 92 {
//                strArray.append(String.init(c))
//            }
//            // 小写字母
//            if a > 96 && a < 123 {
//                strArray.append(String.init(c))
//            }
//            if strArray.count == length {
//                break
//            }
//        }
        let randomStr = strArray.joined(separator: "")
        return randomStr
    }
    
    /// 字符串转化为base64
    public func base64() -> String {
        let data = self.data(using: String.Encoding.utf8)
        let base64Str = data?.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: UInt(0)))
        return base64Str ?? ""
    }
    
    /// MD5加密字符串：32位小写
    public func md5() -> String {
        let cStr = self.cString(using: String.Encoding.utf8)
        let strLen = CUnsignedInt(self.lengthOfBytes(using: String.Encoding.utf8))
        let digestLen = Int(CC_MD5_DIGEST_LENGTH)
        let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
        CC_MD5(cStr!, strLen, result)
        var md5 = String.init()
        for i in 0 ..< digestLen {
            let indexMd5 = String.init(format: "%02x", result[i])
            md5.append(indexMd5)
        }
        free(result)
        return md5
    }
    
    // MARK: func
    
    // FIXME: - 字符串的尺寸
    
    /// 计算字符串的尺寸
    ///
    /// - Parameter font: 字符串的字号
    /// - Returns: 字符串的尺寸
    func stringSize(_ font: UIFont) -> CGSize {
        return self.stringSize(font, 0.0)
    }
    
    /// 计算限制最大宽度字符串的尺寸
    ///
    /// - Parameters:
    ///   - font: 字符串的字号
    ///   - maxWidth: 限制最大宽度
    /// - Returns: 字符串的尺寸
    func stringSize(_ font: UIFont, _ maxWidth: CGFloat) -> CGSize {
        let attributesDic = [NSAttributedString.Key.font : font]
        let size = CGSize.init(width: maxWidth, height: CGFloat(MAXFLOAT))
        return self.boundingRect(with: size, options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: attributesDic, context:nil).size
    }
    
    // MARK: - 文件路径
    
    // FIXME: - 文件路径
    
    /// 获取文件在应用包中的完整路径(如.plist、.bundle等其它不是.swift的文件)
    ///
    /// - Parameters:
    ///   - fileName: 文件名称
    ///   - fileType: 文件扩展名（举例：Info.plist文件：该文件的扩展名为plist）
    /// - Returns: 文件在应用包中的路径
    static func fileFullPath(fileName: String, fileType: String) -> String? {
        return Bundle.main.path(forResource: fileName, ofType: fileType)
    }
    
    // MARK: - 字符串转日期和时间戳
    
    /// 转为日期
    ///
    /// - Returns: 日期
    public func toDate() -> Date {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        return formatter.date(from: self) ?? Date.init()
    }
    
    /// 转为时间戳
    ///
    /// - Returns: 时间戳
    public func toStamp() -> TimeInterval {
        return self.toDate().timeIntervalSince1970
    }
    
    // MARK: - property
    
    // FIXME: - 系统文件夹路径
    
    static var homePath: String {
        get {
            return NSHomeDirectory()
        }
    }
    
    static var documnetsPath: String {
        get {
            //            let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory,
            //                                                            FileManager.SearchPathDomainMask.userDomainMask, true)
            //            let documentsPath = paths.first
            let homePath = NSHomeDirectory()
            let path = homePath + "/Documents"
            return path
        }
    }
    
    static var libraryPath: String {
        get {
            let homePath = NSHomeDirectory()
            let path = homePath + "/Library"
            return path
        }
    }
    
    static var cachesPath: String {
        get {
            let homePath = NSHomeDirectory()
            let path = homePath + "/Library/Caches"
            return path
        }
    }
    
    static var preferencesPath: String {
        get {
            let homePath = NSHomeDirectory()
            let path = homePath + "/Library/Preferences"
            return path
        }
    }
    
    static var systemDataPath: String {
        get {
            let homePath = NSHomeDirectory()
            let path = homePath + "/SystemData"
            return path
        }
    }
    
    static var tmpPath: String {
        get {
            let homePath = NSHomeDirectory()
            let path = homePath + "/tmp"
            return path
        }
    }
    
    // MARK: - 正则表达式字符串判断
    
    /// 是否是手机号码
    public func isPhoneNumber() -> Bool {
        return self.matches(with: "^1\\d{10}$")
    }
    
    /// 是否是密码
    public func isPassword() -> Bool {
        return self.matches(with: "^[a-zA-Z0-9]{6,18}$")
    }
    
    /// 是否是验证码
    public func isCodeNumber() -> Bool {
        return self.matches(with: "^\\d{4}$")
    }
    
    /// 是否是学员号
    public func isStudentNumber() -> Bool {
        return self.matches(with: "^1\\d{8}$")
    }
    /// 是否微信号
    public func isWChat() -> Bool {
        return self.matches(with: "^[a-zA-Z\\d_]{5,}$")
    }
    
    
    private func matches(with pattern: String) -> Bool {
        do {
            let regularExpression = try NSRegularExpression.init(pattern: pattern, options: [])
            let results = regularExpression.matches(in: self, options: [], range: NSRange.init(location: 0, length: self.count))
            return results.count > 0
        } catch _ {
            return false
        }
    }
    
    
    /// 数组转json
    static func getJSONStringFromArray(array:NSArray) -> String {
        if (!JSONSerialization.isValidJSONObject(array)) {
            print("无法解析出JSONString")
            return ""
        }
        let data : NSData! = try? JSONSerialization.data(withJSONObject: array, options: []) as NSData?
        let JSONString = NSString(data:data as Data,encoding: String.Encoding.utf8.rawValue)
        return JSONString! as String
    }
    
    // MARK: - 获取图片链接后的宽高比
    
    /// 获取图片链接后的宽高比
    func getImageScale() -> CGFloat {
        // https://demoapi.anniekids.net/Public/netclass/experienceNew/background.png?w=1178&h=7965
        //        let pattern = "^[a-zA-Z0-9\\u4e00-\\u9fa5\\-\\_\\.]$"
        let subStrigList = self.components(separatedBy: ".png?")
        if subStrigList.count != 2 {
            return 1.0
        }
        let paramList = subStrigList.last?.components(separatedBy: "w=")
        if paramList?.count != 2 {
            return 1.0
        }
        let floadList = paramList?.last?.components(separatedBy: "&h=")
        if floadList?.count != 2 {
            return 1.0
        }
        let width = CGFloat.init(Double.init(floadList?.first ?? "1.0") ?? 1.0)
        let height = CGFloat.init(Double.init(floadList?.last ?? "1.0") ?? 1.0)
        return width/height
    }
    
}
